iT邦幫忙

2025 iThome 鐵人賽

DAY 12
0
自我挑戰組

雲端與資料平台實戰:從抽象概念到落地技術系列 第 12

Day12 GitLab CI:參數解耦與多環境管理實務分享

  • 分享至 

  • xImage
  •  

經過昨天對 GitLab CI 的介紹,相信讀者們已經對如何撰寫 .gitlab-ci.yml 有一定的理解。今天,我想分享一些我在實戰中遇到的問題,並討論如何透過 參數解耦 來降低複雜度,提升管理效率。


實際場景:跨服務共用 Kafka Bootstrap

在實際專案中,我們常常會遇到不同服務需要連線到同一個 Kafka Cluster 的情況,例如:

範例 1:Flink Deployment 使用 Kafka Bootstrap

# flink-values.yaml
flinkDeployment:
  image: flink:latest
  jobManager:
    replicas: 1

# 原始寫法:需直接設定 Kafka Bootstrap
kafkaBootstrap: dev-kafka-bootstrap.svc:9092

範例 2:Kafka Connect Cluster 使用 Kafka Bootstrap

# connect-values.yaml
connectCluster:
  replicas: 3
  image: kafka-connect:latest

# 原始寫法:需直接設定 Kafka Bootstrap
kafkaBootstrap: dev-kafka-bootstrap.svc:9092

這樣的寫法,雖然看似簡單,但問題在於 kafkaBootstrap 實際上是由 Kafka Cluster 的命名規則動態生成的
例如,在 Kafka Chart 的 values.yaml 中:

kafka:
  cluster:
    name: dev-kafka

在模板中,Bootstrap 會根據 cluster name 生成:

bootstrapServers: "{{ .Values.kafka.cluster.name }}-bootstrap.svc:9092"

也就是說,如果我們更改了 Kafka Cluster 名稱,所有使用 Kafka 的服務都需要同步更新,這將大幅增加維護成本與出錯風險。


初步解法:每個服務都複製完整階層

最直觀的想法,是讓每個服務都保留一份 Kafka 的完整階層設定,例如:

kafka:
  cluster:
    name: dev-kafka

這樣模板就能直接引用 .Values.kafka.cluster.name 來生成正確的 bootstrap 名稱。

缺點:

  • 耦合度過高:每個服務都必須保留完整的 Kafka 結構。
  • 管理複雜:一旦 Kafka Cluster 名稱變動,所有服務的 YAML 都需要同步修改。
  • 閱讀負擔大:為了單一變數,卻製造了深層結構,降低可讀性。

更佳解法:參數扁平化 + CI/CD 注入

為了解決上述問題,我們可以將結構進行扁平化,直接在 values.yaml 中使用單一變數,例如:

kafka_cluster_name: dev-kafka

模板中則改寫為:

bootstrapServers: "{{ .Values.kafka_cluster_name }}-bootstrap.svc:9092"

如此一來,所有需要使用 Kafka 的服務都只需要關心 kafka_cluster_name,而不用了解 Kafka 的完整階層結構。


整合 CI/CD:統一變數管理

這個參數可以進一步移至 GitLab CI,由 CI/CD 流程統一注入,達到集中管理的效果。

GitLab CI 設定

variables:
  KAFKA_CLUSTER_NAME: dev-kafka

部署命令

在部署 Kafka 或其他依賴 Kafka 的服務時,統一透過 --set 注入變數:

helm upgrade --install my-kafka ./kafka-chart \
  --set kafka.cluster.name=$KAFKA_CLUSTER_NAME

這樣所有服務只需透過同一個 CI/CD 變數,就能保證環境一致性,並且方便在不同環境中快速切換。


方案優勢

採用此設計後,可以帶來以下三個好處:

  1. 降低耦合度

    • 各服務不需了解 Kafka 的完整結構,只需引用 kafka_cluster_name
    • 避免深層結構帶來的修改連鎖效應。
  2. 集中管理

    • Kafka Cluster 名稱僅需在 GitLab CI 中維護一次。
    • CI/CD 能夠依環境注入不同參數,減少 YAML 檔的重複修改。
  3. 提高可重用性

    • 相同的 Helm Chart 可在不同環境中重複使用。
    • 部署參數可抽換,不需修改原始 Chart。

總的來說,參數層級應依其影響範圍與存活週期來規劃。影響範圍小、變動頻繁的參數適合留在服務本身;而跨服務、長期存在的參數,則應上升到更高層級集中管理。這樣能在彈性與維護成本之間取得平衡,也為後續的部署策略留出更大的擴展空間。


接下來我們來看另一個案例:

**實際場景:Terraform 環境管理

在多環境部署時,常見的做法是將各環境的參數獨立存放,例如 dev.configstaging.configprod.config,並透過 -backend-config 載入:

# 傳統寫法
TF_DIR=/dev/terraform
TF_BACKEND=/dev/terraform/dev.config

cd $TF_DIR
terraform init -backend-config=$TF_BACKEND
terraform plan

這樣做雖然清晰,但會衍生出許多重複的檔案,尤其當環境數量增加時,維護成本也會隨之上升。


另一種方式則是 將環境抽象為變數,在初始化時直接透過參數注入,省去額外的配置檔:

ENV=dev

cd /$ENV/terraform
terraform init \
  -backend-config="bucket=my-bucket" \
  -backend-config="prefix=${ENV}"

terraform plan \
  -var-file="${ENV}.tfvars" \
  -out="tfplan_${ENV}.json"

這種方式不僅減少了檔案管理的複雜度,也讓部署流程更具彈性,可以輕鬆切換不同環境,只需改變 ENV 變數即可完成整個初始化與規劃。

小結:

今天我們從 跨服務 Kafka 參數管理與 Terraform 多環境配置 出發,探討了如何透過參數解耦與變數抽象來降低維護成本:

  • 扁平化參數設計:將深層結構壓平,如 kafka_cluster_name,降低服務間耦合度,並保持模板彈性。
  • CI/CD 統一管理:將跨服務、長期存在的參數集中在 GitLab CI 或部署流程中,方便多環境切換與集中控管。
  • 環境抽象與變數注入:Terraform 範例中,透過 ENV 變數控制初始化與 plan,減少重複檔案,提高部署流程彈性。
  • 依影響範圍與存活週期規劃參數層級:小範圍、短期參數可留在服務本身;跨服務、長期參數則應集中管理,以平衡彈性與維護成本。

透過這些實務策略,我們可以讓部署流程更清晰、可重用,也為後續的多環境管理與自動化提供穩定基礎,
希望今天的內容能帶給各位一些啟發,也歡迎大家分享自己的實務案例,一起討論最佳做法。

感謝各位閱讀,我們明天見!


上一篇
Day11 GitLab CI - .gitlab-ci.yml 實務解析:五大區塊與模組化設計
系列文
雲端與資料平台實戰:從抽象概念到落地技術12
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言